#include "wavewater.h"
#include "qpainter.h"
#include "QMouseEvent"
#include "qtimer.h"
#include "qsize.h"



WaveWater::WaveWater(QWidget *parent) :
    QWidget(parent)
{
    QGridLayout* layout=new QGridLayout(this);
    selectFileBtn=new QPushButton;
    selectFileBtn->setText(QString::fromLocal8Bit("select file"));
    label=new QLabel;
    mainwidget=new QWidget;
    mainwidget->setBaseSize(200,200);
    layout->addWidget(selectFileBtn,0,0);
    layout->addWidget(label,0,1);
    layout->addWidget(mainwidget,1,0,1,2);

    connect(selectFileBtn,&QPushButton::clicked,this,&WaveWater::btn_selected);

    //初始化石头和加载图片
    this->isStopped=true;
    this->isPressed=false;
    this->damping=1;
    this->refractive=0;
    this->stoneSize=0;
    this->stoneWeight=0;

    QString image_path=":/bg.jpg";
    this->imageOrigin=QImage(image_path);
    this->imageRender=QImage(image_path);
    this->image=QPixmap(image_path);

    //初始化buffer
    QPainter* painter=new QPainter;
    painter->setPen(Qt::NoPen);
    painter->drawRect(QRect(0,0,200,200));
    painter->drawImage(0,0,this->imageOrigin);


    timer=new QTimer(this);
    timer->setInterval(5);
    connect(timer,SIGNAL(timerout()),this,SLOT(drawImage()));

}

WaveWater::~WaveWater(){

}

void WaveWater::mouseMoveEvent(QMouseEvent *event){
    this->isPressed=true;

    this->lastPoint=event->pos();
    timer->start();
}

void WaveWater::mousePressEvent(QMouseEvent *event){
    this->isPressed=true;
    this->isStopped=false;

    this->lastPoint=event->pos();
    this->label->setText(QString::number(this->lastPoint.rx())+","+QString::number(this->lastPoint.ry()));
    timer->start();

}

void WaveWater::mouseReleaseEvent(QMouseEvent *){
    this->isPressed=false;

}

void WaveWater::paintEvent(QPaintEvent *){
    if(image.isNull()){
        return;
    }

    QPainter painter(this);
    painter.setRenderHints(QPainter::SmoothPixmapTransform);
    //如果停止阶段则绘制原图，否则绘制渲染图
    if(isStopped){
        painter.drawPixmap(0,0,image);
    }
    else{
        painter.drawPixmap(0,0,pixmap);
    }

}

void WaveWater::drawImage(){
    if(isStopped){
        timer->stop();
    }
    else{
        this->waveRender();
        this->update();
    }
}

void WaveWater::wavaSpread(){
    quint32 counter=0;
    //波能渐变
    for(int h=1;h<imageHeight-1;h++){
        for(int w=1;w<imageWidth-1;w++){
            //波能扩散
            waveBuffer2[w][h]=((waveBuffer1[w-1][h]+waveBuffer1[w+1][h]+
                    waveBuffer1[w][h-1]+waveBuffer1[w][h+1])>>1)-waveBuffer2[w][h];
            //波能衰减
            waveBuffer2[w][h]-=(waveBuffer2[w][h])>>damping;
            //判断波能释放结束
            if(waveBuffer1[w][h]-waveBuffer2[w][h]){
                counter++;
            }
        }
    }
    //交换缓冲区
    int** temp=waveBuffer1;
    waveBuffer1=waveBuffer2;
    waveBuffer2=temp;

    //设置释放完成
    isStopped=counter?false:true;
}

void WaveWater::waveRender(){
    //先改变波纹振幅
    wavaSpread();
    if(isStopped){
        return;
    }

    int offsetX=0;
    int offsetY=0;
    //扫描位图
    for(int y=1;y<imageHeight;y++){
        for(int x=1;x<imageWidth;x++){
            //根据波幅计算位图数据偏移值，渲染点（x,y）对应原始图片的(offsetX,offsetY)
            offsetX=x+((waveBuffer1[x-1][y]-waveBuffer1[x+1][y])>>refractive);
            offsetY=y+((waveBuffer1[x][y-1]-waveBuffer1[x][y+1])>>refractive);
            //复制像素
            if(0<=offsetX && offsetX <imageWidth -1 && 0 <=offsetY && offsetY<imageHeight-1)
            {
                QRgb color=imageOrigin.pixel(offsetX,offsetY);
                imageRender.setPixel(x,y,color);
            }
        }
    }
    pixmap.convertFromImage(imageRender);
}

void WaveWater::dropStone(int x, int y, int stoneSize, int stoneWeight){
    isStopped=false;
    int posX=0;int posY=0;

    for(int h=-stoneSize;h<stoneSize;h++){
        for(int w=-stoneWeight;w<stoneWeight;w++){
            posX=x+w;
            posY=y+h;

            //控制范围,不能超出图片
            if(posX<0 ||posX>=imageWidth || posY<0 || posY>=imageHeight){
                continue;
            }

            //点（w,h）在一个圆形区域内，初始化波能缓冲区
            if(h*h+w*w<=stoneSize*stoneSize){
                waveBuffer1[posX][posY]=-stoneWeight;
            }
        }
    }
}

int WaveWater::getDamping() const{
    return damping;
}


int WaveWater::getRefractive() const{
    return refractive;
}
int WaveWater::getStoneSize() const{
    return stoneSize;
}
int WaveWater::getStoneWeight() const{
    return stoneWeight;
}

QPixmap WaveWater::getImage() const{
    return image;
}

QSize WaveWater::sizeHint() const{
    QSize s(0,0);
    return s;
}
QSize WaveWater::minimumSizeHint() const{
    QSize s(0,0);
    return s;
}


void WaveWater::setDamping(int damping){
    this->damping=damping;
}

void WaveWater::setRefractive(int refractiva){
    this->refractive=refractiva;
}

void WaveWater::setStoneSize(int stoneSize){
    this->stoneSize=stoneSize;
}

void WaveWater::setStoneWeight(int stoneWeight){
    this->stoneWeight=stoneWeight;
}

void WaveWater::setImage(const QPixmap image){
    this->image=image;
}

void WaveWater::btn_selected()
{
    QFileDialog dialog(this);
    dialog.setDirectoryUrl(QUrl("."));
    dialog.setFileMode(QFileDialog::AnyFile);

    if(dialog.exec()){
        auto filelist=dialog.selectedFiles();
        this->filename=filelist[0];
        qDebug()<<this->filename;
        label->setText(this->filename);
        if(this->filename.endsWith(QString(".png"))){
            this->mainwidget->setStyleSheet("border-image:url("+this->filename+");");

            imageOrigin.load(this->filename);
            imageRender.load(this->filename);
            pixmap.load(this->filename);

            this->imageWidth=this->mainwidget->width();
            this->imageHeight=this->mainwidget->height();
//            for(int i=1;i<this->imageHeight;i++){
//                for(int j=1;j<this->imageWidth;j++){
//                    waveBuffer1[j][i]=imageOrigin.pixelIndex(j,i);
//                    waveBuffer2[j][i]=imageOrigin.pixelIndex(j,i);
//                }
//            }
        }
    }
}
